﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;

namespace QaaSimulation.QSim.Ships
{
    public class QShipModel : QModel
    {
        private new QShipBox[,] m_ModelBoxes;

        public void SetModelBox(int x, int y, QShipBox box)
        {
            m_ModelBoxes[x, y] = box;
            if (box != null)
            {
                box.ArrayPosition = new Point(x, y);
            }

            if (x > 0)
                if (m_ModelBoxes[x - 1, y] != null)
                {
                    m_ModelBoxes[x - 1, y].SetNeighbor(QBoxSide.Right, box);
                    if (box != null)
                        box.SetNeighbor(QBoxSide.Left, m_ModelBoxes[x - 1, y]);
                }
            if (x < m_Width - 1)
                if (m_ModelBoxes[x + 1, y] != null)
                {
                    m_ModelBoxes[x + 1, y].SetNeighbor(QBoxSide.Left, box);
                    if (box != null)
                        box.SetNeighbor(QBoxSide.Right, m_ModelBoxes[x + 1, y]);
                }

            if (y > 0)
                if (m_ModelBoxes[x, y - 1] != null)
                {
                    m_ModelBoxes[x, y - 1].SetNeighbor(QBoxSide.Bottom, box);
                    if (box != null)
                        box.SetNeighbor(QBoxSide.Top, m_ModelBoxes[x, y - 1]);
                }
            if (y < m_Height - 1)
                if (m_ModelBoxes[x, y + 1] != null)
                {
                    m_ModelBoxes[x, y + 1].SetNeighbor(QBoxSide.Top, box);
                    if (box != null)
                        box.SetNeighbor(QBoxSide.Bottom, m_ModelBoxes[x, y + 1]);
                }
            CalcModelProperties();
        }

        public QShipBox GetModelBox(int x, int y)
        {
            return m_ModelBoxes[x, y];
        }

        public QShipBox[] GetNeighborhood(int x, int y)
        {
            QShipBox[] res = new QShipBox[4] { null, null, null, null };

            if (x > 0)
                res[(int)QBoxSide.Left] = m_ModelBoxes[x - 1, y];

            if (x < m_Width - 1)
                res[(int)QBoxSide.Right] = m_ModelBoxes[x + 1, y];

            if (y > 0)
                res[(int)QBoxSide.Top] = m_ModelBoxes[x, y - 1];

            if (y < m_Height - 1)
                res[(int)QBoxSide.Bottom] = m_ModelBoxes[x, y + 1];
            return res;
        }


        private PointF m_Centroid;
        public PointF Centroid
        {
            get
            {
                return m_Centroid;
            }
            private set
            {
                m_Centroid = value;
            }
        }

        private int m_TotalCrew;
        public int TotalCrew
        {
            get
            {
                return m_TotalCrew;
            }
            private set
            {
                m_TotalCrew = value;
            }
        }

        private float m_TotalMass;
        public float TotalMass
        {
            get
            {
                return m_TotalMass;
            }
            private set
            {
                m_TotalMass = value;
            }
        }

        private int m_TotalShieldPower;
        public int TotalShieldPower
        {
            get
            {
                return m_TotalShieldPower;
            }
            private set
            {
                m_TotalShieldPower = value;
            }
        }

        private void CalcModelProperties()
        {
            PointF weightedPoint = new PointF();
            float totalWeight = 0;
            int totalShieldPower = 0;
            int crew = 0;
            int energy = 0;
            for (int x = 0; x < m_Width; x++)
                for (int y = 0; y < m_Height; y++)
                {
                    if (m_ModelBoxes[x, y] != null)
                    {
                        QShipBox box = m_ModelBoxes[x, y];
                        crew += box.Crew;
                        energy += box.Energy;
                        weightedPoint.X += (box.ArrayPosition.X * QModelBox.BOX_RELATION + QModelBox.BOX_RELATION / 2f) * box.Mass;
                        weightedPoint.Y += (box.ArrayPosition.Y * QModelBox.BOX_RELATION + QModelBox.BOX_RELATION / 2f) * box.Mass;
                        totalWeight += box.Mass;
                        if (box is QShieldGeneratorBox)
                        {
                            totalShieldPower += ((QShieldGeneratorBox)box).ShieldPower;
                        }
                    }
                }
            m_TotalCrew = crew;
            m_TotalEnergy = energy;
            m_TotalMass = totalWeight;
            m_TotalShieldPower = totalShieldPower;
            if (totalWeight != 0.0f)
            {
                m_Centroid.X = weightedPoint.X / totalWeight;
                m_Centroid.Y = weightedPoint.Y / totalWeight;
            }
            else
                m_Centroid = new PointF(0, 0);
        }

        private int m_TotalEnergy;
        public int TotalEnergy
        {
            get
            {
                return m_TotalEnergy;
            }
            private set
            {
                m_TotalEnergy = value;
            }
        }

        public QShipModel(int _width, int _height)
        {
            m_Width = _width;
            m_Height = _height;
            if (m_Width > 0 && m_Height > 0)
            {
                m_ModelBoxes = new QShipBox[m_Width, m_Height];
            }
        }


        public override void Paint(Graphics g)
        {
            for (int x = 0; x < this.Width; x++)
            {
                for (int y = 0; y < this.Height; y++)
                {
                    QModelBox thisBox = this.GetModelBox(x, y);
                    if (thisBox != null)
                    {
                        GraphicsState state = g.Save();
                        g.TranslateTransform(x * QModelBox.BOX_RELATION - m_Centroid.X, y * QModelBox.BOX_RELATION - m_Centroid.Y);
                        thisBox.Paint(g);
                        g.Restore(state);
                    }
                }
            }
        }
    }
}
